home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CD ROM Paradise Collection 4
/
CD ROM Paradise Collection 4 1995 Nov.iso
/
comms_w
/
twswfwg.zip
/
DIS_PKT.ASM
next >
Wrap
Assembly Source File
|
1994-05-27
|
61KB
|
2,208 lines
TITLE DIS_PKT
; DIS_PKT.ASM - Adapter provides Packet Driver v1.11 interface over NDIS.
; Version 1.07 18 May 1991 by Joe R. Doupnik, Utah State Univ.
; Version 1.08 9 Aug 1991 by Dan Lanciani, ddl@harvard.harvard.edu
; Version 1.09 3 Nov 1991 by Joe R. Doupnik, Utah State Univ.
; Version X.10 6 Nov 1991 by Dan Lanciani, ddl@harvard.harvard.edu
; Version 1.10 5 Feb 1992 by Dan Lanciani, ddl@harvard.harvard.edu
; Version 1.11 31 Dec 1992 by Dan Lanciani, ddl@harvard.harvard.edu
; Copyright (C) 1988 - 1991 FTP Software, Inc.
;
; This unmodified source file and it's executable form may be used and
; redistributed freely. The source may be modified, and the source or
; executable versions built from the modified source may be used and
; redistributed, provided that this notice and the copyright displayed by
; the exectuable remain intact, and provided that the executable displays
; an additional message indicating that it has been modified, and by whom.
;
; FTP Software Inc. releases this software "as is", with no express or
; implied warranty, including, but not limited to, the implied warranties
; of merchantability and fitness for a particular purpose.
;
; USE AT YOUR OWN RISK.
;
; Please send bug reports to ddl@harvard.harvard.edu or
;
; Dan Lanciani
; 185 Atlantic Road
; Gloucester, MA 01930
;
;
; To build, using Microsoft MASM 5 or later, LINK 3.64 or later, and EXE2BIN:
;
; masm dis_pkt;
; link dis_pkt;
; exe2bin dis_pkt.exe dis_pkt.dos
; del dis_pkt.exe
; del dis_pkt.obj
;
;
;What DIS_PKT.DOS does: It provides a Packet Driver
;interface to programs built to operate over Packet Drivers. It talks
;to NDIS (3Com/Microsoft) instead of to a lan board directly. It shares
;the board with NDIS users. We call this a "shim", sitting between the
;normal applications program (NetWare shells, TCP/IP, etc) and the more
;hardware specific portions (NDIS in this case).
;
; Packet Driver flavored applications NDIS flavored applications
; || ||
; ------------- ||
; | DIS_PKT | ||
; ------------- ||
; || ||
; ------------------------------------------
; | main module |
; | NDIS ........................ |
; | board specific driver(s) |
; -------------------------------------------
; ||
; -------------------------
; | Ethernet board(s) |
; -------------------------
; ||
; =========================================== Ethernet wire
;
;
;First sample PROTOCOL.INI file:
;
;[protocol manager]
; drivername = PROTMAN$
;
;[pktdrv] <-- name of this driver entry
; drivername = pktdrv$ <-- formal driver name
; bindings = wd8003xmac <-- use your board's NDIS driver here
; intvec = 0x60 <-- Packet Driver Int, 60h..7fh
; chainvec = 0x66 <-- post-EOI processing interrupt
; novell = y <-- Optional, if present and y(es) then
; convert between old Novell 802.3 pkts
; on the wire and Type 8137 for the app.
; Omitting this line or using any other
; response turns off the conversion;
; default is no conversion.
;
;[attiso]
; drivername = ATTISO$ <-- Another NDIS client
; bindings = wd8003xmac <-- bound to the same harware driver
; nsess = 5
; ncmds = 14
; use_emm = n
;
;Western Digital EtherCard PLUS Family Adapter <-- Ethernet board
;[wd8003xmac] <-- its ndis driver
; drivername = MACWD$
; irq = 7
; ramaddress = 0xCA00
; iobase = 0x280
; receivebufsize = 1536 <-- make this a full Ethernet pkt
;
;
;
;
;Sample section of CONFIG.SYS (StarGROUP material is not required):
;
;device=c:\lanman\protman.sys /i:c:\lanman <-- must be first
;device=c:\lanman\macwd.dos <-- WD8003E driver
;device=c:\lanman\dis_pkt.dos <-- Pkt Driver (this program)
;device=c:\lanman.dos\drivers\attload.dos /Y <-- StarGROUP NDIS
;device=c:\lanman.dos\drivers\attiso\attiso.dos <-- StarGROUP NDIS
;device=c:\qemm\loadhi.sys /r:1 e:\pctcp\ifcust.sys <-- PC/TCP stuff
;device=c:\qemm\loadhi.sys /r:4 e:\pctcp\ipcust.sys <-- etc
;
;
; A second, more elaborate example, with names easier to type. We start with
;file PROTOCOL.INI. Note that semicolons start comment lines.
;
;; This is a sample protocol.ini file listing three Ethernet boards:
;; attcsma.dos is an AT&T StarLAN 10 EN100
;; elnkii.dos is a 3Com 3C503
;; wd8003.dos is a Western Digital WD8003E
;; Only one board will be selected but the other two are present.
;
;[protocol manager]
; drivername = PROTMAN$
;
;; Packet Driver protocol users tie in here
;[pktdrv]
; drivername = pktdrv$
; bindings = attcsma
;; bindings= elnkii
;; bindings = wd8003
; intvec = 0x60
;; chainvec = 0x66
; novell = no ; do not convert packet types this time
;
;; AT&T StarGROUP protocol stack ties in here via name ATTISO$
;[attiso]
; drivername = ATTISO$
; bindings = attcsma
;; bindings = elnkii
;; bindings = wd8003
; nsess = 5
; ncmds = 14
; use_emm = n
;
;;Western Digital EtherCard PLUS Family Adapter, WD8003E in this case
;[wd8003]
; drivername = MACWD$
; irq = 7
; ramaddress = 0xCA00
; iobase = 0x280
; receivebufsize = 1536
;; maxtransmits = 6
;; receivebuffers = 6
;; receivechains = 6
;
;; 3Com Etherlink II, 3C503
;[elnkii]
; drivername = ELNKII$
; ioaddress = 0x350
; interrupt = 5
; transceiver = onboard
; maxtransmits = 12
; xmitbufs = 1
;
;; AT&T StarLAN 10 EN100
;[attcsma]
; drivername = ATTCSMA$
; board_type = 2
; irq = 2
; ioaddr = 0x360
; daram = 0xD000
;
;; End of file protocol.ini
;
;Fragment of config.sys for the second example. Note three .dos board drivers.
;
;device=c:\system\ramdrive.sys 1024 512 128 /E
;device=c:\lanman\protman.sys /i:c:\lanman.dos\drivers\star10en
;device=c:\lanman\attcsma.dos
;device=c:\lanman\elnkii.sys
;device=c:\lanman\macwd.dos
;device=c:\lanman\dis_pkt.dos
;device=c:\lanman.dos\drivers\attload.dos /Y
;device=c:\lanman.dos\drivers\attiso\attiso.dos
;device=c:\qemm\loadhi.sys /r:1 e:\pctcp\ifcust.sys
;device=c:\qemm\loadhi.sys /r:4 e:\pctcp\ipcust.sys
;device=c:\qemm\loadhi.sys /r:4 c:\netdev.sys
;shell=c:\command.com /p /e:800
;
;It is necessary to run NETBIND.EXE to get all this to be active.
;
;
; Edit History
; 06-Jul-89 WJR Changed interface flags in LDT to 2 per Norsk Data
; (may make vector binding work). Changed receive to
; allocate buffer for frame size instead of lookahead
; value. (This will fail miserably if the frame size
; is unknown at upcall time; such is life.) Changed
; SetPacketFilter to use module ID instead of dummy.
; 11-Sep-89 jbvb Clean up, add 1.09 functionality.
; 12-Sep-89 jbvb Don't do interrupt if vector contents are 0.
; 14-Sep-89 wjr Changed frame_rejected to frame_not_recognized to make
; vectored operation work. Changed send_pkt to use
; drv_cct.mod_id. Tried using 0 as protocol id in open
; adapter call. Changed device name to pktdrv$,
; flushed open adapter not supported message.
; 15-Sep-89 wjr Changed open adapter back to CS since 0 broke it.
; 24-Oct-89 wjr Changed FRAME_NOT_RECOGNIZED from 4 to 3
; 07-Feb-90 wjr Added push and pop SI to rcv_chn & rcv_lah.
; 02-Apr-90 wjr Fixed xmt_chn to properly check for request queued
; 03-Apr-90 wjr Given changed TCP, treat REQUEST_QUEUED as success.
; 06-Apr-90 jbvb Update patch level to 2.
; 23-Apr-90 jbvb Don't trash BP, free init code, fix comments.
; 25-Apr-90 jbvb Support "extended" calls: get/set_rcv_mode,
; get_statistics will suffice for LW.
; 26-Apr-90 jbvb Support "match all" on typelen == 0.
; 05-Jun-90 jbvb Fix stack bug in "match all" handling in access_type,
; pass valid CX on 2nd receiver() upcall, version 5.
; 13-Jun-90 jbvb Write basic set_address() code, but comment it out
; because NDIS may require a CloseAdapter first in
; order for it to work. Not worth it to me.
; 27-Jul-90 jbvb Copyright, build instructions, release v1.05.
; 24-Mar-91 jrd Rewrite great chunks to straighen out stack and DS
; addressing. This now works with Novell IPX/NETn
; and Netwatch (together as a matter of fact) and
; with PC/TCP from FTP Inc. Version to 1.06.
; Joe R. Doupnik, jrd@cc.usu.edu, Utah State Univ.
; 30-Mar-91 jrd Allow 10 byte TYPE idents to pick out packets,
; more cleanups, more needed. Promiscuous mode put last.
; Allow 20 handles. Works fine with (NetWare+PC/TCP+
; Netwatch) Pkt Drvr + Lan Man going simulanteously.
; Works with Clarkson issued Packet Driver utilities.
; 18-May-91 jrd Add filtering of packet addresses if running in
; promiscuous mode, add get current Ethernet address
; function to aid filtering, add receive mode indicator
; for each handle, correct error in snd_def initing.
; Correct problem with receive lookahead addressing.
; Compensate for 3Com drivers not preserving regs.
; Bump up NDIS tables to v2. Dis_pkt version to 1.07.
; 09-Aug-91 ddl 802.5, 802.3 support; default binding; overwrite fix
; 03-Nov-91 jrd Add keyword NOVELL to PROTOCOL.INI to convert between
; old Novell 802.3 packets on the wire to 8137 for the
; applications program. Convert if the line is present
; and the value is y(es). Small cleanups.
; 06-Nov-91 ddl Add general macro/routine in support of correct sync
; calls to MAC. Make send_pkt wait for completion.
; Eliminate extra cs: prefixes and consolidate various
; register/register and register/stack operations. Use
; mac_ds for all downcalls. Add MAC open/close routines
; for set_address and Token Ring all-frames mode. Enable
; PD set_address API.
; 08-Nov-91 ddl Eliminate extra register saves and compares. Absorb
; set_packet_filter errors for Token Ring drivers in
; all-frames mode. Allow multiple handles with the
; same type. More cleanup.
; 09-Nov-91 ddl Add deliver routine to handle multiple upcalls per
; packet. Replace broken packet filter code. Various
; code rewrites. Punt blocking send_pkt for WD driver.
; (The WD driver does not generate TransmitConfirms
; within IndicationCompletes and will therefore cause
; deadlock if a blocking send_pkt is attempted.) This
; is a real problem since PD semantics require that
; buffer use is finished when send_pkt completes and
; we cannot guarantee such.
; 10-Nov-91 ddl Remove more unnecessary push/pop code. Assume max
; frame size on ReceiveLookahead with zero length.
; Take advantage of SUCCESS = 0.
; 11-Nov-91 ddl Move Novell code from pktfilter to deliver to avoid
; overwriting card's buffers.
; 12-Nov-91 ddl Simplify packet filter.
; 05-Feb-92 ddl Fix the Novell bug I introduced...
; 31-Dec-92 ddl Another try at sync sends & remove restrictions
; on non-zero vector pointer. The new scheme allows
; you to specify the true hardware interrupt as
; ``chainvec'' in which case dis_pkt does not (of
; course) perform the int. Someday we can get the
; info from NDIS v2 MAC drivers but until then...
PAGE ,80
EOL equ <13, 10, '$'>
LF = 10
CR = 13
EOS = '$'
DOS equ 21h
prstr equ 9
fopen equ 3dh
fclose equ 3eh
ioctl equ 44h
MSG MACRO TEXT
push dx ;; save DX across call
push ax
push ds
mov ax, cs
mov ds, ax
mov dx, offset TEXT ;; point to message
mov ah, prstr ; display dollar terinated string
int dos
pop ds
pop ax
pop dx
ENDM
; Issue a request to the MAC and wait for the result
;
SYNCREQUEST MACRO
mov req_con_flg, REQUEST_QUEUED
call Request
call req_wt
ENDM
; DOS request header offsets
command = 2
status = 3
bpb = 18
end_off = 14
end_seg = 16
; NDIS General Request codes
INIT_DIAG equ 1
READ_ERR_LOG equ 2
SET_STA_ADDR equ 3
OPEN_ADAPTER equ 4
CLOSE_ADAPTER equ 5
RESET_MAC equ 6
SET_PKT_FLT equ 7
ADD_MULT_ADDR equ 8
DEL_MULT_ADDR equ 9
UPDATE_STATS equ 10
CLEAR_STATS equ 11
INTERRUPT_ME equ 12
SET_FUNC_ADDR equ 13
SET_LOOKAHEAD equ 14
ADDR_NONE equ 0 ; NDIS Receiver modes: disabled
ADDR_MULT equ 1 ; Receive packets for my address & multicast
ADDR_BRD equ 2 ; Receive broadcast packets
ADDR_PROM equ 4 ; Receive all packets (promiscuous mode)
ADDR_SRCRT equ 8 ; Receive all source-routed packets
; Protocol to MAC return codes
SUCCESS equ 0
REQUEST_QUEUED equ 2
FRAME_NOT_RECOGNIZED equ 3
INVALID_PARAMETER equ 7
NOT_SUPPORTED equ 9
GENERAL_FAILURE equ 0FFH
; NDIS-related structure definitions
cct_def struc
dw 64 ; Size of common characteristics table (cct)
dw 0 ; Level of cct (zero this version)
dw 0 ; Level of service-specific subtables
db 2 ; Major module version (2 BCD digits)
db 0 ; Minor module version (2 BCD digits)
dd 2 ; Module function flags
db 'PKTDRV$', 9 dup (0) ; Module name, 16 byte ASCIIZ format
db 4 ; Protocol level at upper boundary of module
db 0 ; type of interface at upper module boundary
db 1 ; protocol level at lower boundary of module
db 1 ; type of interface at lower module boundary
mod_id dw -1 ; module ID filled in by Protocol Manager
mod_ds dw 0 ; module DS
system dd 0 ; system request dispatch entry point
sscp dd 0 ; pointer to service-specific characteristics
sssp dd 0 ; pointer to service-specific status
udtp dd 0 ; pointer to upper dispatch table
ldtp dd 0 ; pointer to lower dispatch table
dd 0 ; reserved (must be NULL)
dd 0 ; reserved (must be NULL)
cct_def ends
ssc_def struc
dw 96 ; length of MAC service-specific
; characteristics table (ssc)
mtype db 16 dup (0) ; type name of MAC, ASCIIZ format
dw 0 ; length of station addresses in bytes
db 16 dup (0) ; permanent station address
cur_add db 16 dup (0) ; current station address
dd 0 ; current functional address of adapter
dd 0 ; multicast address list
dd 0 ; link speed
svc_1 dw 0 ; service flags
svc_2 dw 0 ; service flags
maxfram dw 0 ; max frame size both sent and recv
dd 0 ; total transmission buffer cap in driver
dw 0 ; transmission buffer allocation block size
dd 0 ; total reception buffer cap in driver
dw 0 ; reception buffer allocation block size
db 3 dup (0) ; IEEE vendor code (OUI)
db 0 ; vendor adapter code
dd 0 ; vendor adapter description pointer
mirq dw 0 ; IRQ of adapter (NDIS v2)
dw 0 ; transmit queue depth (NDIS v2)
dw 0 ; number of data blocks in buffer desc
ssc_def ends
sss_def struc
dw 0 ; length of status table
dd 0 ; date/time of last diagnostics
lstatus dd 0 ; MAC status
dw 0 ; current packet filter
dd 0 ; pointer to media specific statistics table
dd 0 ; date/time of last ClearStatistics call
r_tot dd 0 ; total frames received
r_crc dd 0 ; frames with CRC error
rb_tot dd 0 ; total bytes received
r_drop dd 0 ; frames discarded - no buffer space
r_mult dd 0 ; multicast frames received
r_bro dd 0 ; broadcast frames received
r_err dd 0 ; frames received with errors
r_big dd 0 ; frames exceeding maximum size
r_runt dd 0 ; frames smaller than minimum size
rb_mul dd 0 ; multicast bytes received
rb_bro dd 0 ; broadcast bytes received
r_hwer dd 0 ; frames discarded - hardware error
x_tot dd 0 ; total frames transmitted
xb_tot dd 0 ; total bytes transmitted
x_mul dd 0 ; multicast frames transmitted
x_bro dd 0 ; broadcast frames transmitted
xb_bro dd 0 ; broadcast bytes transmitted
xb_mul dd 0 ; multicast bytes transmitted
x_tmo dd 0 ; frames not transmitted - time-out
x_hwer dd 0 ; frames not transmitted - hardware error
sss_def ends
udt_def struc ; upper dispatch table
dd 0 ; back pointer to cct
reqadd dd 0 ; request address
xchain dd 0 ; TransmitChain address
dd 0 ; TransferData address
dd 0 ; ReceiveRelease address
indon dd 0 ; IndicationOn address
indoff dd 0 ; IndicationOff address
udt_def ends
ldt_def struc ; lower dispatch table
dd 0 ; back pointer to cct
dd 2 ; interface flags (2 means something)
dd 0 ; RequestConfirm address
dd 0 ; TransmitConfirm address
dd 0 ; ReceiveLookahead indication address
dd 0 ; IndicationComplete address
dd 0 ; ReceiveChain indication address
dd 0 ; status indication address
ldt_def ends
snd_def struc ; transmit buffer descriptor
dw 0 ; byte count of immediate data (always 0)
dd 0 ; address of immediate data
dw 1 ; count of data blocks (always 1)
db 0 ; pointer type (0 == physical)
db 0 ; reserved
snd_len dw 0 ; number of bytes to send
snd_off dw 0 ; offset of data to send
snd_seg dw 0 ; segment of data to send
snd_def ends
rcv_def struc ; receive buffer descriptor
dw 1 ; count of data blocks (always 1)
db 0 ; pointer type (0 == physical)
db 0 ; reserved
rcv_len dw 0 ; number of bytes to get
rcv_off dw 0 ; offset of data to get
rcv_seg dw 0 ; segment of data to get
rcv_def ends
req_def struc ; Request block - Protocol Manager primitives
req_opc dw 0 ; opcode for PM request
req_sta dw 0 ; status returned from request
req_of1 dw 0 ; first parameter pointer
req_sg1 dw 0
req_of2 dw 0 ; second parameter pointer
req_sg2 dw 0
req_prm dw 0 ; parameter word
req_def ends
bnd_def struc ; binding list
bnd_cnt dw 1 ; number of MACs to bind to -- 0 or 1
bnd_nam db 16 dup (0) ; name of module to bind to
bnd_def ends
SUBTTL Resident Data Area
PAGE
CSEG SEGMENT PARA PUBLIC 'CODE'
assume cs:CSEG, ds:CSEG, es:nothing
; DEVICE HEADER - must be at offset zero within device driver
dd -1 ; becomes pointer to next device header
dw 8000H ; attribute (char device)
dw offset strat ; pointer to device strategy routine
dw offset intr ; pointer to device interrupt handler
db "PKTDRV$ " ; device driver name
; END OF DEVICE HEADER
mac_cctp dd 0 ; address of MAC's cct table
mac_ds dw 0 ; DS register for MAC
drv_cct cct_def <> ; Common Characteristics Table
drv_ldt ldt_def <> ; Lower Dispatch Table
drv_snd snd_def <> ; Argument blocks for NDIS TransmitChain,
drv_rcv rcv_def <> ; TransferData,
drv_bnd bnd_def <> ; and Bind (via DOS IOCTL)
drv_req req_def <> ; Argument block for general NDIS requests
TransmitChain dd 0 ; MAC entry point to send packet
TransferData dd 0 ; MAC entry point for data copy
Request dd 0 ; MAC entry point for requests
;ReceiveRelease dd 0 ; MAC entry point (???not used???)
IndicationOn dd 0 ; MAC entries to control Indications
IndicationOff dd 0 ; (upcalls) from NDIS
req_con_flg dw 0 ; Completion status from NDIS upcall
xmt_cmp dw 0 ; TransmitChain result
init_flg db 0 ; Non-zero if we've been initialized
address db 6 dup (0) ; Current address from MAC
novell db 0 ; if non-zero convert between old
; Novell 802.3 interior to Type 8137
; Caller used 8137, wire gets 802.3
nd_mode dw 3 ; Current NDIS packet filter
; Request Header (RH) address, saved here by "strategy" routine
req_hdr label dword
req_off dw 0
req_seg dw 0
; Save the request header for use by the interrupt routine
strat PROC FAR
mov word ptr cs:req_off, bx ; offset
mov word ptr cs:req_seg, es ; segment
ret
strat ENDP
EVEN ; Get into word alignment
;;
;; Data for Packet Driver
;;
BAD_HANDLE equ 1 ; invalid handle number
NO_CLASS equ 2 ; no interfaces of this class found
NO_TYPE equ 3 ; no interfaces of specified type found
NO_NUMBER equ 4 ; no interfaces of specified number found
BAD_TYPE equ 5 ; bad packet type specified
NO_MULTICAST equ 6 ; this interface does not support multicast
CANT_TERMINATE equ 7 ; this packet driver cannot terminate
BAD_MODE equ 8 ; an invalid receiver mode was specified
NO_SPACE equ 9 ; operation failed because of insufficient space
TYPE_INUSE equ 10 ; type had previously been accessed and not released
BAD_COMMAND equ 11 ; the command was out of range or not implemented
CANT_SEND equ 12 ; the packet couldn't be sent (usually hardware error)
CANT_SET equ 13 ; The hardware address couldn't be changed
BAD_ADDRESS equ 14 ; Hardware address has bad length or format
CANT_RESET equ 15 ; Couldn't reset interface (more than 1 handle open)
PD_LEVEL equ 6 ; Implementation level (basic, high perf, ext)
ANY_TYPE equ 0ffffh ; Matches any if_type
ETHERADDR_LEN equ 6 ; Length of an Ethernet address
; The connection arrays: types, and corresponding upcalls
PD_MAX_CONNS equ 20 ; The maximum number of handles/Types that can
; be registered at one time
MAX_P_LEN equ 10 ; max length of TYPE matching field, bytes
per_handle struc ; Packet Driver HANDLE structure
pd_conn_used db 0 ; non-zero if this handle is in use
pd_conn_type db MAX_P_LEN dup(0) ; associated packet type
pd_conn_type_len dw 0 ; associated packet type length
pd_conn_rmode dw 3 ; receive mode for this handle
pd_conn_rcvr dd 0 ; receiver handler address
pd_conn_class db 0 ; interface class
per_handle ends
handles per_handle PD_MAX_CONNS dup(<>)
end_handles label byte
if_class db 1 ; Class 1 is Ethernet
if_type equ 57 ; NDIS to Packet Driver adapter
pd_version equ 11 ; Version
pd_vector dw -1 ; Packet Driver vector to serve on
pd_rcv_mode dw 3 ; Default to rcv mode 3 (normal/bcast)
pd_name db "MAC/DIS converter", 0
matchoff dw 12 ; offset to match bytes
addroff dw 0 ; offset to addresses
multimask db 1 ; multicast
; Table re-maps (badly) NDIS modes to Packet Driver modes (in parentheses)
ndis_mode db 0 ; No packets (0 == illegal)
db 0 ; No packets (1 == receiver off)
db 1 ; Directed | Multicast (2 should be directed only)
db 3 ; Directed | Multicast | Broadcast
; (3 should be directed | broadcast)
db 3 ; Directed | limited Multicast | Broadcast
; (4 == directed | broadcast | limited multicast)
db 3 ; Directed | limited Multicast | Broadcast
; (5 should be directed | broadcast | all multicast)
db 4 ; Promiscuous (6 == match all)
EVEN ; Get into word alignment
; struct param; Pointer to this returned by get_parameters()
pd_param db 1 ; Major revision = 1
db 9 ; Minor revision = 9
db 14 ; Length of this structure = 14
db ETHERADDR_LEN ; MAC addr length
mtu dw 1514 ; MAC packet length
dw 0 ; No multicast support
dw 0 ; No promises re: back-to-back receives
dw 0 ; No promises re: back-to-back transmits
param_int dw 0 ; Default to no interrupt on EOI
; Pointer to this returned by get_statistics
pd_statistics struc
pkt_in dd 0 ; Total packets in
pkt_out dd 0 ; Total packets out
bytes_in dd 0 ; Total bytes received
bytes_out dd 0 ; Total bytes sent
errs_in dd 0 ; Total transmit errors
errs_out dd 0 ; Total receive errors
pkts_lost dd 0 ; Packets dropped - no buffer, out of resc
pd_statistics ends
pd_stat pd_statistics <> ; An instance of the above
PUBLIC driver_info, access_type, release_type, send_pkt, terminate
PUBLIC get_address, reset_interface, get_parameters, set_rcv_mode
PUBLIC get_rcv_mode, get_statistics, set_address
; Normal (basic Packet Driver functions) Jump Table
pd_table dw pd_none ; No handler
dw driver_info ; 1
dw access_type ; 2
dw release_type ; 3
dw send_pkt ; 4
dw terminate ; 5
dw get_address ; 6
dw reset_interface ; 7
pd_table_size equ ($-pd_table)/2
; High Performance functions Jump Table
hp_table dw get_parameters ; 10
dw pd_none ; 11 (as_send_pkt not implemented)
hp_table_size equ ($-hp_table)/2
; Extended functions Jump Table
ext_table dw set_rcv_mode ; 20
dw get_rcv_mode ; 21
dw pd_none ; 22 (set_multicast_list not implemented)
dw pd_none ; 23 (get_multicast_list not implemented)
dw get_statistics ; 24
dw set_address ; 25
ext_table_size equ ($-ext_table)/2
;
; rcv_lah is the proc that handles ReceiveLookAhead upcalls from the MAC
;
; First, it determines if the packet is one that is wanted. If so, it asks
; the appropriate application for a buffer. If it gets one, it copies the
; data and makes the 2nd call to the application to post it complete. If
; not, it returns SUCCESS to the DIS driver anyway. It returns SUCCESS if
; if the packet was copied or FRAME_NOT_RECOGNIZED if it is not in the list
; of desired types.
;
;The stack coming into this call is:
; dw bp[20] MACID
; dw bp[18] framesize
; dw bp[16] bytes available in buffer
; dw bp[14] lookahead data address seg
; dw bp[12] lookahead data address off
; dd bp[10] indicate flag
; dw bp[6] ds of called protocol mode (ME)
;
rcv_lah PROC FAR
push bp
mov bp, sp
push si ; -2[bp]
push di ; -4[bp]
push ds ; -6[bp]
sub sp, 2 ; -8[bp] return count
mov ax, cs ; setup data segment
mov ds, ax
cld
cmp word ptr 18[bp], 0 ; unknown frame size
jnz lah_have_size
mov ax, mtu
mov 18[bp], ax ; try for max
lah_have_size:
les dx, 12[bp]
mov bx, offset handles - size per_handle
call pktfilter ; apply packet filter
jnc lah_have_buf ; nc = we want this packet
mov ax, FRAME_NOT_RECOGNIZED ; packet not accepted
jmp lah_don
lah_have_buf:
push bx
lea ax, -8[bp] ; get scratch location
push ss ; to put bytes copied into
push ax ; and push it
xor ax, ax ; Starting offset in frame
push ax ; is always zero
;
; Set up recv table description
;
mov ax, 18[bp] ; Len of recv data
mov drv_rcv.rcv_len, ax ; goes in argument descriptor
mov drv_rcv.rcv_seg, es ; as does far address of
mov drv_rcv.rcv_off, di ; receive buffer
push ds ; Push far pointer to
mov ax, offset drv_rcv ; descriptor
push ax
push mac_ds ; Push MAC's DS value
call TransferData ; Copy pkt to buf (pops args)
;
; Call Packet Driver receive routine again (AX = 1) to finish up
;
pop bx ; recover handle
lds si, dword ptr drv_rcv.rcv_off
call deliver ; run all the upcalls
xor ax, ax
lah_don:add sp, 2 ; local material
pop ds
pop di
pop si
pop bp
ret 16 ; Pop MAC's params off stack
rcv_lah ENDP
;
; rcv_chn is the proc that handles ReceiveChain upcalls from the MAC
;
; First, it determines if the packet is one that is wanted.
; It returns success if the packet is ok or FRAME_NOT_RECOGNIZED if it is not
; in the list of currently open types.
;
; The stack coming into this call is:
; dw bp[20] MACID
; dw bp[18] framesize
; dw bp[16] request handle
; dw bp[14] receive-chain buf descriptor address seg
; dw bp[12] receive-chain buf descriptor address off
; dd bp[8] indicate flag addr
; dw bp[6] DS of called protocol mode (ME)
;
; where receive-chain buffer descriptor format is
; dw rxdatacount count of received data blocks, max of 8
; dw rxdatalen length of a data block
; dd rxdataptr seg:offset of a data block
rcv_chn PROC FAR
push bp
mov bp, sp
push si ; -2[bp]
push di ; -4[bp]
push ds ; -6[bp]
mov ax, cs ; setup data segment (== CS)
mov ds, ax
cld
les di, 12[bp]
les dx, es:[di+4] ; es:di is now the buffer pointer
mov bx, offset handles - size per_handle
call pktfilter ; apply packet filter, return handle
jnc chn_have_buf ; nc = we want this packet
mov ax, FRAME_NOT_RECOGNIZED ; packet not accepted
jmp chn_don
chn_have_buf:
push es ; Save ES:DI (pointer) to pass
push di ; back to receiver later
lds si, 12[bp] ; Addr of rcv descriptor
mov cx, [si] ; Get number of data blocks
add si, 2 ; & move to top of list
chn_dat: ; Move data from next block into stack's buffer
push cx
push ds
push si
mov cx, [si] ; Get byte count of block
add si, 2
lds si, [si] ; Get far pointer to data
shr cx, 1
jnc rcvchn5 ; nc = even already
movsb ; Move 1 byte if count is odd
rcvchn5:rep movsw ; Use word mov for efficiency
pop si ; Go through rest of chain
add si, 6
pop ds
pop cx
loop chn_dat ; For all blocks
;
; Call Packet Driver receive routine again to finish up
;
pop si ; DS:SI = buffer pointer
pop ds
call deliver ; run all the upcalls
xor ax, ax
chn_don:pop ds
pop di
pop si
pop bp
ret 16 ; pop params off stack
rcv_chn ENDP
; Worker for lookahead and receive_chain procedures above. Checks PD handles
; for wanting this kind of packet. Returns carry clear, BX = handle,
; and ES:DI = buffer if packet is wanted, else carry set to reject the packet.
; If the adapter is in promiscuous mode (and the handle is not) we make an
; attempt at software filtering. This is intentionally incomplete: clients
; will be subjected to multicast packets that they may not want if any
; other client asks the adapter to accept multicast packets. Therefore,
; there is no point in trying to avoid this situation in promiscuous mode.
; Later might want to add full filtering for all modes.
;
; Note that search starts at the handle *following* BX. Expects lookahead
; pointer in ES:DX and packet length in 18[bp].
;
pktfproc proc near
nohnd: stc
ret
pktfilter:add bx, size per_handle ; next entry
cmp bx, offset end_handles
jnc nohnd
cmp [bx].pd_conn_used, 0 ; is handle in use?
jz pktfilter
mov cx, [bx].pd_conn_type_len ; number of bytes to match
jcxz foundhnd
lea si, [bx].pd_conn_type ; TYPE wanted by this handle
mov di, dx ; es:di is lookahead data ptr
cmp if_class, 3
jnz norif
test byte ptr es:8[di], 80h
jz norif
mov al, es:14[di]
and ax, 1fh
add di, ax
norif: add di, matchoff
cmp novell, 0
jz compare
cmp word ptr es:2[di], 0ffffh
jnz compare
cmp word ptr [si], 3781h
jnz compare
cmp cx, 2 ; paranoia
jnz compare
mov ax, es:[di]
xchg ah, al
cmp ax, 1501
jc foundhnd
compare:repz cmpsb
jnz pktfilter
foundhnd:cmp pd_rcv_mode, 6 ; board in promiscuous mode
jnz nofil
cmp [bx].pd_conn_rmode, 6 ; but handle is not--filter
jz nofil
mov cx, ETHERADDR_LEN
mov si, offset address ; our address
mov di, dx
add di, addroff
mov al, multimask ; multicast/broadcast bit
test es:[di], al
jnz nofil
repe cmpsb
jz nofil
jmp pktfilter
nofil: mov cx, 18[bp] ; recover length
xor ax, ax
push es
push dx
push bp
push bx
call [bx].pd_conn_rcvr ; ask for a buffer
cli
cld
pop bx
pop bp
pop dx
mov ax, es
or ax, di
jnz havebuf
pop es
jmp pktfilter ; no luck--continue search
havebuf:pop ax
clc
ret
pktfproc endp
; Deliver data to all interested handles following BX, then to BX itself.
; Data to be delivered in DS:SI, length in 18[bp].
;
deliver proc near
push bx
; do old Novell 802.3 to Type 8137
cmp cs:novell, 0 ; doing old Novell conversion?
je deliver0 ; e = no
push si
add si, cs:matchoff
cmp word ptr [si+2], 0ffffh ; have the bad DSAP/SSAP signature?
jne noconv ; ne = no
mov ax, [si] ; get length/Type field value
xchg ah, al ; low endian form
cmp ax, 1501 ; size is larger than length?
jnc noconv
mov word ptr [si], 3781h ; force in Novell Type 8137
noconv: pop si
; end of Novell section
deliver0:push ds
push si
mov ax, ds
mov es, ax
mov dx, si
mov ax, cs
mov ds, ax
call pktfilter ; find next potential client
pop si
pop ds
mov ax, 1
mov cx, 18[bp]
jc deliver2
push ds
push si
push es
push di
push cx
shr cx, 1
jnc deliver1
movsb
deliver1:rep movsw ; copy between clients
pop cx
pop si
pop ds
push bx
push bp
call cs:[bx].pd_conn_rcvr ; "secondary" client
cli
cld
pop bp
pop bx
pop si
pop ds
jmp short deliver0
deliver2:pop bx
call cs:[bx].pd_conn_rcvr ; run the final upcall
cld
ret
deliver endp
;
; Services indication complete upcall
;
; Executes interrupt (returned by get_parameters()) to pass control to
; an application which wants to run after the EOI.
;
; NOTE: Interrupt number at label ind_int is over-written if a different
; interrupt is configured in protocols.ini.
;
ind_com PROC FAR ; Indication_complete upcall
push es
push bx
mov bx, cs:param_int ; Get offset of vector
cmp bx, 16
jc ind_no_int
xor ax, ax
mov es, ax ; Point ES at interrupt segment
shl bx, 1 ; Multiply by 4 for memory offset
shl bx, 1
cmp word ptr es:[bx]+2, 0 ; Is there a segment there?
jne ind_int ; ne = yes
cmp word ptr es:[bx], 0 ; Is there an offset there?
je ind_no_int ; no, no interrupt
ind_int: ; INT 65 overwritten if selected
INT 65h ; Pass control to the application
ind_no_int:
pop bx ; Restore registers
pop es
xor ax, ax
ret 4
ind_com ENDP
;;;;;;;;;;;;;;;;;;;;;;;;; Packet Driver section
regs struc ; stack offsets of incoming regs
_ES dw ?
_DS dw ?
_BP dw ?
_DI dw ?
_SI dw ?
_DX dw ?
_CX dw ?
_BX dw ?
_AX dw ?
_IP dw ?
_CS dw ?
_F dw ? ; flags, Carry flag is bit 0
regs ends
bytes struc ; stack offsets of incoming regs
dw ? ; es, ds, bp, di, si are 16 bits
dw ?
dw ?
dw ?
dw ?
_DL db ?
_DH db ?
_CL db ?
_CH db ?
_BL db ?
_BH db ?
_AL db ?
_AH db ?
bytes ends
CY equ 0001h ; to set caller's carry bit
;
; Interrupt handler for the Packet Driver interface (protocol stack downcalls)
;
; NOTE: Leaves interrupts disabled on entry - code in access_type and
; release_type depends on this. send_pkt enables interrupts for MAC.
;
PUBLIC pd_isr
pd_isr PROC FAR
jmp short over ; skip the string (this MUST be a 3 byte jmp)
nop ; make three bytes
db "PKT DRVR", 0 ; string to identify a packet driver
over:
push ax
push bx
push cx
push dx
push si
push di
push bp
push ds
push es
cld
push cs ;set up ds to this code segment
pop ds
mov bp, sp ;we use bp to access the original regs
and _F[bp], not CY ;start by clearing the carry flag
mov _DH[bp], 0 ; put no-error code in caller's DH
cmp ah, pd_table_size ; AH too large?
jae highperf_table ; ae = yes, try next set
; Dispatch on AH using normal table
mov bl, ah ; Get function code
xor bh, bh ; into a word register
shl bx, 1 ; index by words
jmp pd_table[bx] ; and go
highperf_table:
sub ah, 10 ; Offset of 1st high-performance function
jl pd_none ; l = ah is out of range
cmp ah, hp_table_size ; is AH still in range?
jae xtend_table ; ae = no, try next set
; Dispatch on AH using high-performance table
mov bl, ah ; Get function code
xor bh, bh ; into a word register
shl bx, 1 ; index by words
jmp hp_table[bx] ; and go
xtend_table:
sub ah, 10 ; Offset of 1st extended function
jl pd_none ; l = AH is not in range
cmp ah, ext_table_size ; still in range?
jae pd_none ; ae = no
; Dispatch on AH using extended table
mov bl, ah ; Get function code
xor bh, bh ; into a word register
shl bx, 1 ; index by words
jmp ext_table[bx] ; and go
pd_none:
mov dh, BAD_COMMAND ; set error code
err_ret:
mov _DH[bp], dh ; put error code in caller's DH
or _F[bp], CY ; set caller's carry flag
good_ret: ; good return (carry clear)
pop es
pop ds
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
iret
;
; Checks the handle in BX. If out of range or not valid cleans up the
; stack and jumps directly to err_ret with a BAD_HANDLE error. Assumes
; called with DS pushed and a near call. If handle is good, just returns.
; BX is shifted one bit to the left.
;
; Bounds check on handle
chk_hdl PROC NEAR
mov bx, _BX[BP] ; Handle
cmp bx, offset handles ; start of handles area
jb chkhdl1 ; b = out of range
cmp bx, offset end_handles ; end of handles area
jae chkhdl1 ; ae = above max table size
cmp [bx].pd_conn_used, 0 ; is handle used?
je chkhdl1 ; e = no, go bomb out
ret ; return BX as handle
chkhdl1:
pop ds ;clear stack (was the return address)
mov dh, BAD_HANDLE ;return BAD_HANDLE error
jmp err_ret
chk_hdl ENDP
; The following implement the individual Packet Driver commands, basic
; functions first.
;
; Send a packet.
; If Novell mode is active, user's buffer may be altered. XXX
;
send_pkt:mov es, _DS[bp] ; get ds of data block to es
mov ax, _CX[bp]
mov drv_snd.snd_len, ax
mov si, _SI[bp]
push drv_cct.mod_id ; put our module id
mov ax, 1
push ax
; do conversion of Type 8137 to old Novell 802.3
cmp novell, 0 ; doing Novell packet conversion?
je send_pkt3 ; e = no
cmp word ptr es:[si+12], 3781h ; outgoing Novell Type 8137?
jne send_pkt3 ; ne = no
mov ax, es:[si+12+4] ; get internal length indicator
xchg ah, al
inc ax ; round up to an even length
and al, not 1
xchg ah, al
mov es:[si+12], ax ; change packet Type field to length
send_pkt3:mov drv_snd.snd_off, si ; store offset of pkt buffer
mov drv_snd.snd_seg, es ; store segment of pkt buffer
mov bx, offset drv_snd ; get addr of xmit buff desc
push ds ; store on stack
push bx
push mac_ds ; MACID
mov xmt_cmp, REQUEST_QUEUED ; set up for queued data
call TransmitChain ; do downcall to NDIS
sti ; enable ints just to be sure
xor cx, cx
send_pkt6:or ax, ax
jz send_pkt4
cmp ax, REQUEST_QUEUED ; queued?
jne send_pkt5 ; ne = no
mov ax, xmt_cmp
loop send_pkt6 ; XXX waiting breaks WD driver
send_pkt4:jmp good_ret
send_pkt5:mov dh, CANT_SEND ; trouble, fail
jmp err_ret
;
; Handle driver_info() downcall - return driver information.
;
driver_info:
mov ch, if_class ; CH is class
xor cl, cl ; CL is interface number (always 0)
mov _BX[bp], pd_version
mov _CX[bp], cx
mov _DX[bp], if_type
mov _SI[bp], offset pd_name ; ds:si is ptr to name
mov _DS[bp], ds
mov _AX[bp], PD_LEVEL
jmp good_ret
;
; Handle access_type() - sets up to handle an Ethernet packet type.
;
; NOTE: Depends on entry with interrupts disabled for shared data locking.
;
access_type_class:
mov dh, NO_CLASS
jmp err_ret
access_type_number:
mov dh, NO_NUMBER
jmp err_ret
access_type_bad:
mov dh, BAD_TYPE
jmp err_ret
access_type:
mov al, if_class
cmp _AL[bp], al ; our class?
jne access_type_class ; ne = no, fail
; cmp _BX[bp], ANY_TYPE ; generic type?
; je access_type_1 ; e = yes
; cmp _BX[bp], if_type ; our type?
; je access_type_1 ; e = yes
; mov dh, NO_TYPE
; jmp err_ret
;access_type_1:
cmp _DL[bp], 0 ; our number?
jne access_type_number ; ne = no
cmp _CX[bp], MAX_P_LEN ; is the type length too long?
ja access_type_bad ; a = yes, this can't be ours
; look for a free handle
mov bx, offset handles ; first handle
access_type_2:
cmp [bx].pd_conn_used, 0 ; is this handle in use?
jz access_type_3
add bx, (size per_handle) ; go to the next handle
cmp bx, offset end_handles ; examined all handles?
jb access_type_2 ; b = no, continue
mov dh, NO_SPACE
jmp err_ret
access_type_3:
mov [bx].pd_conn_used, 1 ; remember that we're using it
mov ax, _DI[bp] ; get receiver address from ES:DI
mov word ptr [bx].pd_conn_rcvr, ax ; offset part
mov ax, _ES[bp]
mov word ptr [bx].pd_conn_rcvr+2, ax ; segment part
push ds
mov ax, ds
mov es, ax
mov ds, _DS[bp] ; remember their type
mov si, _SI[bp]
mov cx, _CX[bp]
mov es:[bx].pd_conn_type_len, cx ; remember the TYPE length
lea di, [bx].pd_conn_type
rep movsb ; copy TYPE field to match
pop ds
mov al, _AL[bp] ; remember Class
mov [bx].pd_conn_class, al
mov [bx].pd_conn_rmode, 3
mov _AX[bp], bx ; return handle in caller's AX
jmp good_ret
;
; Perform release_type() - forget the packet type/upcall/handle
;
; NOTE: Depends on entry with interrupts disabled for shared data locking.
;
release_type:
call chk_hdl ; get handle, return here if ok
; This is a critical region!!
mov [bx].pd_conn_used, 0 ; free handle-used indicator
jmp good_ret
;
; Perform terminate() - never actually do it.
;
terminate:
call chk_hdl ; check handle
mov dh, CANT_TERMINATE ; Return error
jmp err_ret
;
; Perform get_address() - get the current Ethernet address of the interface
;
get_address:
cmp _CX[bp], ETHERADDR_LEN ; Make sure it's an ethernet address
jc get_address_err
call get_eaddr
mov di, _DI[bp]
mov es, _ES[bp]
mov si, offset address
mov cx, ETHERADDR_LEN
rep movsb
mov _CX[bp], ETHERADDR_LEN
jmp good_ret
get_address_err:
mov dh, NO_SPACE ; hmmm, I suppose it's close enough
jmp err_ret
; Return board's current Ethernet address in address (ETHERADDR_LEN bytes)
; via NDIS information.
get_eaddr proc near
push ds
mov di, cs
mov es, di
mov di, offset address
lds si, mac_cctp ; get address of mac cct
lds si, sscp[si] ; get address of mac ssc
add si, cur_add ; mov to offset in structure
mov cx, ETHERADDR_LEN ; get length
cld
rep movsb ; copy address
pop ds
ret
get_eaddr endp
;
; Perform reset_interface() - this is ignored.
;
reset_interface:
call chk_hdl ; check handle
jmp good_ret ; if the handle was good, call is good
;
; The following implement the High Performance functions
;
; get_parameters() - Return pointer to parameters structure in ES:DI
;
get_parameters:
mov _ES[bp], cs ; return struct adr in caller's ES:DI
mov _DI[bp], offset pd_param
jmp good_ret ; & pass it to caller
;
; as_send_pkt() - Not implemented.
;
;as_send_pkt:
; mov dh, BAD_COMMAND
; jmp err_ret
;
; The following implement the Extended functions
;
; set_rcv_mode translates the PDS mode to an NDIS Packet Filter.
;
set_rcv_mode:
call chk_hdl ; get handle, return here if ok
mov cx, _CX[bp]
jcxz set_rcv_mode_err ; z = illegal receive mode, quit
cmp cx, 6 ; is mode legal?
ja set_rcv_mode_err ; a = no, quit
mov bx, cx ; Put it in an index register
mov bl, ndis_mode[bx] ; and translate it for NDIS
xor bh, bh
call set_ndis_mode ; Try to set it
jz set_rcv_mode_ok
set_rcv_mode_err:
mov dh, BAD_MODE ; no, return error
jmp err_ret
set_rcv_mode_ok:
mov bx, _BX[bp] ; get handle again
mov cx, _CX[bp]
mov [bx].pd_conn_rmode, cx ; set receive mode in handle's struct
mov pd_rcv_mode, cx ; save the mode we just set
jmp good_ret ; and return ok
;
; Return the current Packet Driver receive mode.
;
get_rcv_mode:
call chk_hdl ; get handle, return here if ok
mov ax, [bx].pd_conn_rmode ; get mode for this handle
mov _AX[bp], ax
jmp good_ret ; return it
get_statistics:
les si, mac_cctp ; ES:SI == address of NDIS cct
les si, es:sssp[si] ; ES:SI == address of NDIS sss
mov ax, es
or ax, ax ; Is the segment non-zero?
jnz getsta1 ; nz = yes, accept it
or si, si ; how about offset?
jnz getsta1 ; nz = ok
mov dh, BAD_COMMAND ; If they don't implement it,
jmp err_ret ; neither do we
getsta1:mov ax, cs
mov ds, ax
mov di, offset pd_stat ; Get start of PD stats table
cli ; Don't allow updates just now
mov ax, word ptr es:r_tot[si] ; Copy total received frames
mov dx, word ptr es:r_tot+2[si]
call valchk
mov ax, word ptr es:x_tot[si] ; Copy total xmitted frames
mov dx, word ptr es:x_tot+2[si]
call valchk
mov ax, word ptr es:rb_tot[si] ; Copy total received bytes
mov dx, word ptr es:rb_tot+2[si]
call valchk
mov ax, word ptr es:xb_tot[si] ; Copy total transmitted bytes
mov dx, word ptr es:xb_tot+2[si]
call valchk
mov ax, word ptr es:r_err[si] ; Copy total receive errors
mov dx, word ptr es:r_err+2[si]
call valchk
mov ax, word ptr es:x_hwer[si] ; Copy total transmit errors
mov dx, word ptr es:x_hwer+2[si]
call valchk
mov ax, word ptr es:r_drop[si] ; Copy total receives dropped
mov dx, word ptr es:r_drop+2[si]
call valchk
sti ; All done with shared data
mov _SI[bp], offset pd_stat ; set caller's DS:SI to the
mov ax, cs ; address of Packet Driver stats
mov _DS[bp], ax
jmp good_ret
; Convert double word dx:ax from NDIS unknown value of (long) -1 to (long) 0,
; store results in ds:[di, di+2], move di forward two words.
valchk proc near
cmp ax, -1 ; starting at -1 (NDIS, for unknown)?
jne valchkx ; ne = no
cmp dx, -1 ; this part too
jne valchkx ; ne = no
xor ax, ax ; zero counters for zero based counts
xor dx, dx
valchkx:mov [di], ax ; store results locally
mov [di+2], dx
add di, 4 ; step to next storage double word
ret
valchk endp
;
; Perform set_address() - change physical address of the interface.
;
set_address:
cmp _CX[bp], ETHERADDR_LEN ; Make sure it's an ethernet address
jne set_address_err ; Jump if bad length
call close_m
push drv_cct.mod_id ; Make set station address call
mov ax, 1
push ax ; Push request ID (0 to not conf)
xor ax, ax
push ax ; Must be 0
push _ES[bp] ; Push pointer to address to set
push _DI[bp]
mov ax, SET_STA_ADDR ; SetStationAddress function code
push ax
push mac_ds
SYNCREQUEST
jnz set_err
call open_m
call get_eaddr
jmp good_ret
set_err:
call open_m
call get_eaddr ; just in case
mov dh, CANT_SET
jmp err_ret
set_address_err:
mov dh, BAD_ADDRESS ; We didn't like the address
jmp err_ret
pd_isr ENDP
;;;;;; end of Packet Driver direct support procedures
;
; The following are upcalls from DIS:
; RequestConfirm enters with stack of (after our push bp)
; dw [BP+16] ProtID
; dw [BP+14] MACID
; dw [BP+12] ReqHandle
; dw [BP+10] Status
; dw [BP+8] Request
; dw [BP+6] ProtDS (our DS)
req_con PROC FAR ; Request Confirm
push bp
mov bp, sp
mov ax, [bp+10] ; get NDIS status response
mov cs:req_con_flg, ax ; store in local area
pop bp
xor ax, ax
ret 12
req_con ENDP
; Wait for a (possibly) queued request to complete & return result.
; Z flag is set if success.
req_wt PROC NEAR
sti
req_wt1:cmp ax, REQUEST_QUEUED
jnz req_wt2
mov ax, req_con_flg
jmp short req_wt1
req_wt2:or ax, ax
ret
req_wt ENDP
; TransmitConfirm enters with stack of (after our push bp)
; dw [BP+14] ProtID
; dw [BP+12] MACID
; dw [BP+10] ReqHandle
; dw [BP+8] Status
; dw [BP+6] ProtDS (our DS)
xmt_con PROC FAR ; Transmit Confirm
push bp
mov bp, sp
mov ax, 8[bp]
mov cs:xmt_cmp, ax ; moves the return code into static
pop bp
xor ax, ax
ret 10
xmt_con ENDP
sta_ind PROC FAR ; Status handled, not used
xor ax, ax
ret 12
sta_ind ENDP
dis_pat PROC FAR ; System entry point for pkt driver
push bp ; Used only by initiate bind request
mov bp, sp
cmp word ptr 8[bp], 1 ; Is it initiate_bind?
je dispat1 ; e = yes
mov ax, GENERAL_FAILURE ; NO: fail
pop bp
ret 14
dispat1:push ds ; save stuff
push es
push bx
push cx
push si
push di
mov ax, cs ; set up DS == CS
mov ds, ax
les bx, 12[bp]
mov word ptr mac_cctp, bx
mov word ptr mac_cctp + 2, es
mov ax, offset drv_cct ; push pkt drv cct (our cct)
push ds
push ax
mov ax, offset mac_cctp ; push addr for MAC's cct
push ds
push ax
xor ax, ax ; pad parameter
push ax
mov ax, 2 ; Load Bind command code
push ax
push es:[bx].mod_ds
call dword ptr es:[bx].system ; call MAC's system entry point
or ax, ax
jz dispat2 ; z = Bind succeeded
MSG bad_bind ; tell the user the bad news
jmp rtn_dis ; Bind failed, fatal error
dispat2:
call sav_mac ; Save MAC entry point addresses
les bx, mac_cctp ; Check if OpenAdapter needed
les bx, es:[bx].sscp
lea di, [bx].mtype
mov si, offset t8023
mov cx, offset t8023e - offset t8023
cld
repe cmpsb
jz is8023
lea di, [bx].mtype
mov si, offset t8025
mov cx, offset t8025e - offset t8025
repe cmpsb
jz is8025
jmp short gottype
is8023: mov if_class, 11
mov matchoff, 14
jmp short gottype
is8025: mov if_class, 3
mov matchoff, 14
mov addroff, 2
mov multimask, 80h
mov ax, es:[bx].maxfram
mov mtu, ax
; jmp short gottype
gottype:call open_m
jz open_ok1 ; skip to setting packet filter
MSG bad_open_adpt ; Fatal error: open adapter failed
jmp rtn_dis
open_ok1:
push mac_ds
call IndicationOff
push mac_ds
call IndicationOn
sti
call get_eaddr
mov bx, 3 ; Set default filter: Directed,
call set_ndis_mode ; Multicast & Broadcast (3)
jz set_vec
MSG bad_set_pkt ; show an error and fail
jmp rtn_dis
; Give warning if the Packet Driver vector is already in use but use anyway
set_vec:
xor ax, ax ; Set ES to 0 to look in int tab
mov es, ax
mov bx, cs:pd_vector ; Get vector and multiply by 4
shl bx, 1
shl bx, 1
mov es:[bx], offset pd_isr
mov es:2[bx], cs
xor ax, ax
rtn_dis:
pop di ; all done
pop si
pop cx
pop bx
pop es
pop ds
pop bp
ret 14
dis_pat ENDP
; Make the NDIS SetPktFilter call (both at bind and from set_rcv_mode)
;
; Arguments:
; BX NDIS Packet filter to set (see DIS p 45 for bits)
; * 0 - directed and multicast
; * 1 - broadcast
; 2 - promiscuous
; 3 - any source routing packet
;
; Some Token Rind drivers work in all-frames mode (even though they reject
; the set_packet_filter call) as long as the appropriate argument is passed
; to open_adapter. The set_packet_filter error is ignored here for such
; cases.
;
set_ndis_mode PROC NEAR
mov ax, nd_mode
xor ax, bx
and ax, 4 ; changing to/from promiscuous mode
jz set_ndis_mode1
push bx
call close_m
pop bx
set_ndis_mode1:
mov nd_mode, bx
push drv_cct.mod_id ; make set packet filter call
mov ax, 1
push ax ; unique handle (0 to not conf)
push bx ; Push packet filter value
xor ax, ax
push ax ; dd pad
push ax
mov ax, SET_PKT_FLT ; SetPacketFilter command
push ax
push mac_ds
SYNCREQUEST
push ax
call open_m
pop ax
cmp ax, INVALID_PARAMETER ; Absorb error...
jnz set_ndis_mode2
cmp if_class, 3 ; for Token Ring...
jnz set_ndis_mode2
test nd_mode, 4 ; in promiscuous mode only.
jz set_ndis_mode2
xor ax, ax
set_ndis_mode2:
or ax, ax
ret ; NDIS return code is in AX
set_ndis_mode ENDP
; Open the MAC if appropriate. Pass flags for Token Ring all-frames
; mode as necessary.
;
open_m PROC NEAR
les bx, mac_cctp
les bx, es:[bx].sscp
test es:[bx].svc_1, 0800h ; supports open
jz open_m1
les bx, mac_cctp
les bx, es:[bx].sssp
test word ptr es:[bx].lstatus, 010h ; already open
jnz open_m1
push drv_cct.mod_id
mov ax, 1
push ax
xor ax, ax
cmp if_class, 3 ; for Token Ring
jnz open_m2
test nd_mode, 4 ; in promiscuous mode
jz open_m2
mov ax, 6
open_m2:push ax
xor ax, ax
push ax
push ax
mov ax, OPEN_ADAPTER
push ax
push mac_ds
SYNCREQUEST
ret
open_m1:xor ax, ax
ret
open_m ENDP
; Close the MAC if appropriate.
;
close_m PROC NEAR
les bx, mac_cctp
les bx, es:[bx].sscp
test es:[bx].svc_1, 0800h ; supports open
jz close_m1
les bx, mac_cctp
les bx, es:[bx].sssp
test word ptr es:[bx].lstatus, 010h ; not open
jz open_m1
push drv_cct.mod_id
mov ax, 1
push ax
xor ax, ax
push ax
push ax
push ax
mov ax, CLOSE_ADAPTER
push ax
push mac_ds
SYNCREQUEST
ret
close_m1:xor ax, ax
ret
close_m ENDP
;
; Put MAC entry points into static locations - called at bind time.
;
sav_mac PROC NEAR
les si, mac_cctp
mov ax, es:[si].mod_ds ; save MAC ds
mov mac_ds, ax
les si, es:[si].udtp
mov bx, offset Request ; save request entry point
mov ax, es:4[si]
mov [bx], ax
mov ax, es:6[si]
mov 2[bx], ax
mov bx, offset TransmitChain ; save xmt block entry point
mov ax, es:8[si]
mov [bx], ax
mov ax, es:10[si]
mov 2[bx], ax
mov bx, offset TransferData ; save xfer data entry point
mov ax, es:12[si]
mov [bx], ax
mov ax, es:14[si]
mov 2[bx], ax
; mov bx, offset ReceiveRelease ; save recv rel entry point
; mov ax, es:16[si]
; mov [bx], ax
; mov ax, es:18[si]
; mov 2[bx], ax
mov bx, offset IndicationOn ; save ind on entry point
mov ax, es:20[si]
mov [bx], ax
mov ax, es:22[si]
mov 2[bx], ax
mov bx, offset IndicationOff ; save ind off entry point
mov ax, es:24[si]
mov [bx], ax
mov ax, es:26[si]
mov 2[bx], ax
ret
sav_mac ENDP
; Message strings needed at bind time.
bad_open_adpt db "Adapter did not open", EOL
bad_set_pkt db "Set packet filter failed", EOL
bad_bind db 7, "BIND failed", EOL
t8023 db '802.3', 0
t8023e:
t8025 db '802.5', 0
t8025e:
end_res: ;;;; Currently not keeping init code in memory
;
; DOS device driver interrupt entry point.
;
; This is used to initialize module and read parameters from PROTOCOLS.INI
; only, and frees itself after startup. The NDIS bind takes place later,
; via dis_pat and its friends above.
;
intr PROC FAR
push es ; save all registers
push ds
push si
push di
push dx
push cx
push bx
push ax
mov ax, cs ; check to see if already initialized
mov ds, ax
mov al, init_flg ; our init flag
or al, al ; not inited yet (0)?
jz intr1 ; z = yes, init now
mov bx, req_off ; already initialized - return
mov ds, req_seg ; with error
mov [bx].status, 810Ch
jmp rtn
intr1: cli ; not initialized - switch to new
mov si, ss ; stack and init
mov dx, sp
mov ax, cs
mov ss, ax
mov sp, offset new_stk ; Need a big stack for this call
sti ; Critical region
push si ; Save old SS
push dx ; and SP
MSG msg_copyright ; Display copyright notice
call init ; Init this driver
mov ax, cs ; Set DS == CS
mov ds, ax
mov bx, req_off ; Get request header ptr
mov es, req_seg
mov word ptr es:[bx].status, 0100h ; Set return status ok
mov init_flg, 1 ; Note that we've initialized
mov ax, offset end_res ; Set end of resident code
mov word ptr es:[bx].end_off, ax
mov ax, cs
mov es:[bx].end_seg, ax
pop di ; Old SP
pop si ; and old SS
cli ; Critical region
mov ss, si ; Change back to old stack
mov sp, di
sti ; End critical region
rtn: pop ax ; All done
pop bx
pop cx
pop dx
pop di
pop si
pop ds
pop es
ret
intr ENDP
db 512 dup (0)
new_stk label word ; A stack for init to use
db 4 dup (0)
fil_han dw 0 ; File handle for init
;
; Initialize the converter module - read parameters from PROTOCOLS.INI.
;
init PROC NEAR
mov ax, cs ; open the Protocol Manager driver
mov ds, ax
mov ah, fopen ; open file
mov al, 0C2h
mov dx, offset pm__nam ; device name
int dos
jnc init1 ; nc = success
MSG pro_no_open ; error
jmp init_err
init1: mov fil_han, ax ; file handle
mov bx, ax
mov ax, cs
mov ds, ax
mov drv_req.req_opc, 1 ; make GetProtocolManagerInfo call
mov drv_req.req_sta, -1 ; zero out return status
mov drv_req.req_of1, -1 ; NULL out pointers
mov drv_req.req_sg1, -1
mov drv_req.req_of2, -1 ; NULL out pointer 2
mov drv_req.req_sg2, -1
mov drv_req.req_prm, -1 ; zero out parameter word
mov ah, ioctl ; IOCTL req
mov al, 02h ; device input
mov dx, offset drv_req ; pointer to buffer
mov cx, 14 ; size of buffer
int dos ; call DOS
jnc init2 ; nc = success
MSG pro_bad_gpm ; Error: print msg & bomb
jmp init_err
init2: mov ax, cs ; restore ds
mov ds, ax
mov ax, offset pro_nam ; Get name of module to bind to,
push ax ; returned by get_pro in ES:DI
mov ax, pro_nam_len
push ax
mov ax, offset pro_bnd_to
push ax
mov ax, pro_bnd_to_len
push ax
xor ax, ax
push ax
call get_pro ; Try to find the token we want
or di, di ; Was it there?
jnz init4 ; nz = yes, parse it
mov drv_bnd.bnd_cnt, 0 ; else say nothing bound
jmp short init45
init4: push ds ; Save name in bindings structure
push ds ; currently allowed to bind to only
push es ; one MAC
pop ds
pop es
mov si, di
mov di, offset drv_bnd.bnd_nam
mov cx, -2[si]
cld
rep movsb
pop ds
init45: mov ax, offset pro_nam ; Get Packet Driver vector to use
push ax
mov ax, pro_nam_len
push ax
mov ax, offset pro_prm_vec ; "INTVEC" keyword
push ax
mov ax, pro_prm_vec_len
push ax
xor ax, ax
push ax
call get_pro ; Go look for the token
or di, di ; Was the token found?
jnz init5 ; nz = yes
MSG vec_not_spc ; abort if not found
jmp init_err
init5: mov dx, es:[di] ; check that vector is in range
cmp dx, 80h ; 0x80 is high limit
jge bad_vec2
cmp dx, 60h ; 0x60 is low limit
jl bad_vec2
mov pd_vector, dx ; Save value for bind time
jmp short init6 ; Go on to EOI interrupt
bad_vec2:
MSG msg_bad_vec ; Abort if out of range
jmp init_err
init6: mov ax, offset pro_nam ; Get EOI interrupt (if any)
push ax
mov ax, pro_nam_len
push ax
mov ax, offset pro_daisy_vec ; "CHAINVEC" key word
push ax
mov ax, pro_daisy_len
push ax
xor ax, ax
push ax
call get_pro ; Try to find the token
or di, di
jz init7 ; z = no interrupt
mov dx, es:[di] ; Check that interrupt is ok
mov byte ptr ind_int+1, dl ; Modify the code
mov param_int, dx ; Save interrupt number
init7: mov ax, offset pro_nam ; Get old Novell 802.3 keyword
push ax
mov ax, pro_nam_len
push ax
mov ax, offset pro_novell ; "NOVELL" key word
push ax
mov ax, pro_nov_len
push ax
xor ax, ax
push ax
mov novell, 0 ; assume no token
call get_pro ; Try to find the token
or di, di
jz init8 ; z = no token
mov dx, es:[di] ; get the token's value
and dl, not 20h ; to upper case
cmp dl, 'Y' ; "yes"?
jne init8 ; ne = no conversion
mov novell, 1 ; set flag
MSG novmsg ; tell the user about conversion
init8: call pkt_ptr ; Initialize the LDT and CCT pointers
mov ax, cs
mov ds, ax
mov drv_req.req_opc, 2 ; RegisterModule call
mov drv_req.req_sta, 0 ; zero out return status
mov drv_req.req_of1, offset drv_cct ; cct pointer
mov drv_req.req_sg1, ax
mov drv_req.req_of2, offset drv_bnd
mov drv_req.req_sg2, ax
mov drv_req.req_prm, 0 ; zero out parameter word
mov ah, ioctl ; IOCTL call
mov al, 2
mov dx, offset drv_req
mov cx, 14
mov bx, fil_han
int dos
cmp drv_req.req_sta, SUCCESS
je init9 ; e = success
MSG reg_mod_nok
jmp init_err
init9: mov bx, fil_han ; Close protman device
mov ah, fclose
int dos
jc init10 ; c = failure
xor ax, ax ; Indicate success
ret ; & do normal return
init10: MSG msg_err_clo ; close failed, quite unlikely
jmp init_err
init_err:mov ax, 1 ; error return
ret
init ENDP
; get_pro returns a pointer to the keyword entry from GPMI call
; 12[bp] is a pointer to module name
; 10[bp] is length of module name
; 8[bp] is a pointer to keyword name
; 6[bp] is length of keyword name
; 4[bp] is number of parameter wanted from specified keyword
;
; returns
; es:bx is pointer to param
; ax zero for ok and !0 for not found
;
get_pro PROC NEAR
push bp
mov bp, sp
push ds
push bx
push si
lds bx, dword ptr drv_req.req_of1 ; ConMemIma pointer
mov ax, cs ; find module name
mov es, ax
getpro1:mov ax, ds ; quit if pointer NULL (eol)
or ax, ax
jz err_get_pro ; z = error
mov di, 12[bp] ; module name
mov si, bx ; set up to point name
add si, 8
mov cx, 10[bp] ; module name length
cld
repe cmpsb ; right module name?
je pro_fnd ; e = module name found
lds bx, dword ptr [bx] ; not found-load next in chain
jmp short getpro1
pro_fnd:
add bx, 24 ; offset of parameter pointers
getpro2:
mov ax, ds
or ax, ax
jz err_get_pro
mov di, 8[bp] ; parameter name
mov cx, 6[bp] ; parameter name length
mov si, bx
add si, 8
cld
repe cmpsb
je key_fnd ; e = parameter found
lds bx, dword ptr [bx] ; not found-load next in chain
jmp short getpro2
key_fnd:
add bx, 24 ; offset of values
mov cx, 4[bp] ; check if enough values are
cmp cx, [bx] ; here
jge err_get_pro
add bx, 2 ; position to the value
jcxz prm_fnd ; may be either char string
getpro3: ; or number depending on type
add bx, 2
add bx, [bx]
add bx, 2
loop getpro3
prm_fnd:
mov si, bx ; set es:di to point to value
add si, 4
mov cx, 2[bx]
mov ax, ds
mov es, ax
mov di, si
jmp short getpro4
err_get_pro:
; MSG pro_not_fnd ; error return
xor ax, ax
mov es, ax
mov di, ax
getpro4:
pop si ; common return
pop bx
pop ds
pop bp
ret 10
get_pro ENDP
pkt_ptr PROC NEAR ; Set up pointers in Packet
mov ax, cs ; Driver ldt and cct
mov ds, ax ; Note:most of this could
mov bx, offset drv_ldt ; (should) be done statically
mov word ptr [bx], offset drv_cct ; driver's cct back pointer
mov 2[bx], ax
add bx, 8 ; skip int flgs
mov [bx], offset req_con ; RequestConfirm address
mov 2[bx], ax
mov 4[bx], offset xmt_con ; TransmitConfirm address
mov 6[bx], ax
mov 8[bx], offset rcv_lah ; ReceiveLookahead indication
mov 10[bx], ax
mov 12[bx], offset ind_com ; IndicationComplete address
mov 14[bx], ax
mov 16[bx], offset rcv_chn ; ReceiveChain indication add
mov 18[bx], ax
mov 20[bx], offset sta_ind ; status indication address
mov 22[bx], ax
mov bx, offset drv_cct.ldtp ; set up point to drv ldt
mov word ptr [bx], offset drv_ldt
mov 2[bx], ax
;
;set up pointers in pkt driver cct
; only doing lower dispatch table, all other left NULL
; hopefully this will work
;
mov drv_cct.mod_id, -1
mov drv_cct.mod_ds, ax
mov bx, offset drv_cct.system
mov [bx], offset dis_pat ; drv system func entry point
mov 2[bx], ax ; drv ds
mov word ptr 16[bx], offset drv_ldt ; ptr to ldt
mov 18[bx], ax
ret
pkt_ptr ENDP
; Text messages that can be flushed after startup but before bind.
msg_no_vect db "Vector not specified", EOL
msg_bad_vec db "Invalid vector (must be 60h-7Fh)", EOL
msg_err_clo db "Error closing MAC driver", EOL
msg_copyright db "MAC/DIS to Packet Driver converter loaded."
db " Version 1.11", CR, LF
db "Copyright 1991 FTP Software, Inc. All rights "
db "reserved.", cr, lf
db " v1.07 by Joe R. Doupnik, jrd@cc.usu.edu, "
db "Utah State Univ, 18 May 1991", cr, lf
db " v1.09 by Joe R. Doupnik, jrd@cc.usu.edu, "
db "Utah State Univ, 3 Nov 1991", cr, lf
db " v1.08, v1.10, v1.11 by"
db " Dan Lanciani, ddl@harvard.edu", EOL
pm__nam db "protman$", 0
pro_no_open db "Protocol Manager not present", EOL
pro_bad_gpm db "GetProtocolManagerInfo call failed", EOL
pro_nam db "PKTDRV", 0
pro_nam_len equ $ - pro_nam
pro_prm_vec db "INTVEC", 0
pro_prm_vec_len equ $ - pro_prm_vec
pro_daisy_vec db "CHAINVEC", 0
pro_daisy_len equ $ - pro_daisy_vec
pro_prm_nok db "SINTVECXX", 0
pro_prm_nok_len equ $ - pro_prm_nok
pro_bnd_to db "BINDINGS", 0
pro_bnd_to_len equ $ - pro_bnd_to
pro_novell db "NOVELL", 0
pro_nov_len equ $ - pro_novell
novmsg db "Using OLD NOVELL 802.3 packets on the wire", EOL
vec_not_spc db "Interrupt vector for Packet Driver not specifed"
db " in PROTOCOL.INI", EOL
reg_mod_nok db "Register module call failed", EOL
CSEG ends
end